package com.duoqin.chat;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import android.provider.BaseColumns;
import android.text.TextUtils;

import com.duoqin.chat.utils.ChatConfig;
import com.duoqin.common.utils.Utils;

import java.io.File;


public final class Chat implements Parcelable {

    //////////////////////////////
    // Column definitions
    //////////////////////////////
    public static class Columns implements BaseColumns {
        /**
         * The content:// style URL for chat table
         */
        public static final Uri CONTENT_URI =
                Uri.parse("content://com.duoqin.chat/chat");

        /**
         * The content:// style URL for favorite chat table
         */
        public static final Uri FAVORITE_CONTENT_URI =
                Uri.parse("content://com.duoqin.chat/favorite_chat");
        /**
         * weChat id (instead of name)
         * <P>Type: STRING</P>
         */
        public static final String NAME = "name";
        /**
         * type, sent or received
         * <P>Type: STRING</P>
         */
        public static final String TYPE = "type";
        /**
         * True if message is read
         * <P>Type: BOOLEAN</P>
         */
        public static final String READ = "read";
        /**
         * True if message is sent successfully
         * <P>Type: BOOLEAN</P>
         */
        public static final String SENT = "sent";
        /**
         * Message type, text or voice
         * <P>Type: STRING</P>
         */
        public static final String MESSAGE_TYPE = "message_type";
        /**
         * message_text
         * <P>Type: STRING</P>
         */
        public static final String MESSAGE_TEXT = "message_text";
        /**
         * local media path
         * <P>Type: STRING</P>
         */
        public static final String MEDIA_PATH = "media_path";
        /**
         * server media path
         * <P>Type: STRING</P>
         */
        public static final String SERVER_MEDIA_PATH = "server_media_path";
        /**
         * Voice length, in milliseconds
         * <P>Type: INTEGER</P>
         */
        public static final String VOICE_LENGTH = "voice_length";
        /**
         * Timestamp, time of this chat message
         * <P>Type: INTEGER</P>
         */
        public static final String TIME_STAMP = "time_stamp";

        /**
         * The default sort order for this table
         */
        public static final String DEFAULT_SORT_ORDER =
                TIME_STAMP + " ASC";

        public static final String[] CHAT_QUERY_COLUMNS = {
                _ID, NAME, TYPE, READ, SENT, MESSAGE_TYPE, MESSAGE_TEXT, MEDIA_PATH,
                SERVER_MEDIA_PATH, VOICE_LENGTH, TIME_STAMP
        };

        /**
         * These save calls to cursor.getColumnIndexOrThrow()
         * THEY MUST BE KEPT IN SYNC WITH ABOVE QUERY COLUMNS
         */
        public static final int CHAT_ID_INDEX = 0;
        public static final int CHAT_NAME_INDEX = 1;
        public static final int CHAT_TYPE_INDEX = 2;
        public static final int CHAT_READ_INDEX = 3;
        public static final int CHAT_SENT_INDEX = 4;
        public static final int CHAT_MESSAGE_TYPE_INDEX = 5;
        public static final int CHAT_MESSAGE_TEXT_INDEX = 6;
        public static final int CHAT_MEDIA_PATH_INDEX = 7;
        public static final int CHAT_SERVER_MEDIA_PATH_INDEX = 8;
        public static final int CHAT_VOICE_LENGTH_INDEX = 9;
        public static final int CHAT_TIME_STAMP_INDEX = 10;

        public static final String CHAT_TYPE_OUT = "out";
        public static final String CHAT_TYPE_IN = "in";
        public static final String CHAT_MESSAGE_TYPE_TEXT = "text";
        public static final String CHAT_MESSAGE_TYPE_VOICE = "voice";
    }
    //////////////////////////////
    // End column definitions
    //////////////////////////////

    // Public fields
    public long       id;
    public String     name;
    public String     type; // sent or received
    public boolean    read; // read or not
    public boolean    sent; // sent success or not
    public String     message_type; // text, voice, etc
    public String     message_text;
    public String     media_path; // local media file path
    public String     server_media_path; // server media file path
    public long       voice_length;
    public long       time_stamp;

    public static final Creator<Chat> CREATOR = new Creator<Chat>() {
        @Override
        public Chat createFromParcel(Parcel in) {
            return new Chat(in);
        }

        @Override
        public Chat[] newArray(int size) {
            return new Chat[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    public Chat(String sender) {
        id = -1;
        name = sender;
        type = Columns.CHAT_TYPE_OUT;
        read = true;
        sent = false;
        message_type = null;
        message_text = null;
        media_path = null;
        server_media_path = null;
        voice_length = 0;
        time_stamp = System.currentTimeMillis();
    }

    public Chat(Cursor c) {
        id = c.getLong(Columns.CHAT_ID_INDEX);
        name = c.getString(Columns.CHAT_NAME_INDEX);
        type = c.getString(Columns.CHAT_TYPE_INDEX);
        read = c.getInt(Columns.CHAT_READ_INDEX) == 1;
        sent = c.getInt(Columns.CHAT_SENT_INDEX) == 1;
        message_type = c.getString(Columns.CHAT_MESSAGE_TYPE_INDEX);
        message_text = c.getString(Columns.CHAT_MESSAGE_TEXT_INDEX);
        media_path = c.getString(Columns.CHAT_MEDIA_PATH_INDEX);
        server_media_path = c.getString(Columns.CHAT_SERVER_MEDIA_PATH_INDEX);
        voice_length = c.getLong(Columns.CHAT_VOICE_LENGTH_INDEX);
        time_stamp = c.getLong(Columns.CHAT_TIME_STAMP_INDEX);
    }

    public Chat(Chat c) {
        id = -1;
        name = c.name;
        type = c.type;
        read = c.read;
        sent = c.sent;
        message_type = c.message_type;
        message_text = c.message_text;
        media_path = c.media_path;
        server_media_path = c.server_media_path;
        voice_length = c.voice_length;
        time_stamp = c.time_stamp;
    }

    public Chat(Parcel p) {
        id = p.readLong();
        name = p.readString();
        type = p.readString();
        read = p.readInt() == 1;
        sent = p.readInt() == 1;
        message_type = p.readString();
        message_text = p.readString();
        media_path = p.readString();
        server_media_path = p.readString();
        voice_length = p.readLong();
        time_stamp = p.readLong();
    }

    @Override
    public void writeToParcel(Parcel p, int flags) {
        p.writeLong(id);
        p.writeString(name);
        p.writeString(type);
        p.writeInt(read ? 1 : 0);
        p.writeInt(sent ? 1 : 0);
        p.writeString(message_type);
        p.writeString(message_text);
        p.writeString(media_path);
        p.writeString(server_media_path);
        p.writeLong(voice_length);
        p.writeLong(time_stamp);
    }

    /**
     * Queries chat messages
     * @return cursor for chat messages
     */
    public static Cursor getChatCursor(ContentResolver contentResolver, String selection,
                                       String[] selectionArgs) {
        return contentResolver.query(Columns.CONTENT_URI, Columns.CHAT_QUERY_COLUMNS,
                selection, selectionArgs, Columns.DEFAULT_SORT_ORDER);
    }

    public static Chat getChat(ContentResolver contentResolver, String chatId) {
        Cursor cursor = contentResolver.query(
                Columns.CONTENT_URI, Columns.CHAT_QUERY_COLUMNS,
                Columns._ID + "=?", new String[] {chatId}, Columns.DEFAULT_SORT_ORDER);
        if (cursor != null && cursor.moveToFirst()) {
            Chat chat = new Chat(cursor);
            cursor.close();
            return chat;
        } else {
            return null;
        }
    }

    public static Chat getChatByTimeStamp(ContentResolver contentResolver, long timestamp) {
        Cursor cursor = contentResolver.query(
                Columns.CONTENT_URI, Columns.CHAT_QUERY_COLUMNS,
                Columns.TIME_STAMP + "=?", new String[] {timestamp + ""}, null);
        if (cursor != null && cursor.moveToFirst()) {
            Chat chat = new Chat(cursor);
            cursor.close();
            return chat;
        } else {
            return null;
        }
    }

    public static int getUnreadChatCount(ContentResolver contentResolver, String name) {
        int count = 0;
        String SELECTION = Columns.NAME + "=? AND " + Columns.TYPE + "=? AND " + Columns.READ + "=0";
        Cursor cursor = contentResolver.query(
                Columns.CONTENT_URI, Columns.CHAT_QUERY_COLUMNS,
                SELECTION, new String[] {name, Columns.CHAT_TYPE_IN}, null);
        if (cursor != null) {
            count = cursor.getCount();
            cursor.close();
        }
        return count;
    }

    public static Uri insert(ContentResolver contentResolver, Chat chat) {
        ContentValues contentValues = new ContentValues();
        contentValues.put(Columns.NAME, chat.name);
        contentValues.put(Columns.TYPE, chat.type);
        contentValues.put(Columns.READ, chat.read);
        contentValues.put(Columns.SENT, chat.sent);
        contentValues.put(Columns.MESSAGE_TYPE, chat.message_type);
        contentValues.put(Columns.MESSAGE_TEXT, chat.message_text);
        contentValues.put(Columns.MEDIA_PATH, chat.media_path);
        contentValues.put(Columns.SERVER_MEDIA_PATH, chat.server_media_path);
        contentValues.put(Columns.VOICE_LENGTH, chat.voice_length);
        contentValues.put(Columns.TIME_STAMP, chat.time_stamp);
        return contentResolver.insert(Columns.CONTENT_URI, contentValues);
    }

    public static int update(ContentResolver contentResolver, Uri contentUri, Chat chat) {
        ContentValues contentValues = new ContentValues();
        contentValues.put(Columns.NAME, chat.name);
        contentValues.put(Columns.TYPE, chat.type);
        contentValues.put(Columns.READ, chat.read);
        contentValues.put(Columns.SENT, chat.sent);
        contentValues.put(Columns.MESSAGE_TYPE, chat.message_type);
        contentValues.put(Columns.MESSAGE_TEXT, chat.message_text);
        contentValues.put(Columns.MEDIA_PATH, chat.media_path);
        contentValues.put(Columns.SERVER_MEDIA_PATH, chat.server_media_path);
        contentValues.put(Columns.VOICE_LENGTH, chat.voice_length);
        contentValues.put(Columns.TIME_STAMP, chat.time_stamp);
        return contentResolver.update(contentUri, contentValues,
                Columns._ID + "=?", new String[] {chat.id + ""});
    }

    public static int delete(ContentResolver contentResolver, Uri contentUri, Chat chat) {
        if (chat.media_path != null) {
            File file = new File(chat.media_path);
            if (file.exists()) {
                file.delete();
            }
        }
        return contentResolver.delete(contentUri,
                Columns._ID + "=?", new String[] {chat.id + ""});
    }

    public static int deleteAll(ContentResolver contentResolver, Uri contentUri) {
        if (Columns.CONTENT_URI.equals(contentUri)) {
            Utils.clearFolderFiles(ChatConfig.getMessageFolderPath());
        } else if (Columns.FAVORITE_CONTENT_URI.equals(contentUri)) {
            Utils.clearFolderFiles(ChatConfig.getFavoriteFolderPath());
        }
        return contentResolver.delete(contentUri, null, null);
    }

    public static void deleteContact(ContentResolver contentResolver, String name) {
        String SELECTION = Columns.NAME + "=?";
        Cursor cursor = contentResolver.query(Columns.CONTENT_URI, Columns.CHAT_QUERY_COLUMNS,
                SELECTION, new String[] {name}, null);
        if (cursor != null && cursor.moveToFirst()) {
            do {
                String filePath = cursor.getString(Columns.CHAT_MEDIA_PATH_INDEX);
                if (!TextUtils.isEmpty(filePath)) {
                    File file = new File(filePath);
                    if (file.exists()) {
                        file.delete();
                    }
                }
            } while (cursor.moveToNext());
            cursor.close();
            contentResolver.delete(Columns.CONTENT_URI, SELECTION, new String[] {name});
        }
    }

    public static int markAsSent(ContentResolver contentResolver, String timeStamp) {
        ContentValues contentValues = new ContentValues();
        contentValues.put(Columns.SENT, "1");
        return contentResolver.update(Columns.CONTENT_URI, contentValues,
                Columns.TIME_STAMP + "=?", new String[] {timeStamp});
    }

    public static int clearServerMediaPath(ContentResolver contentResolver, String chatId) {
        ContentValues contentValues = new ContentValues();
        contentValues.put(Columns.SERVER_MEDIA_PATH, "");
        return contentResolver.update(Columns.CONTENT_URI, contentValues,
                Columns._ID + "=?", new String[] {chatId});
    }

    public static Uri addToFavorite(ContentResolver contentResolver, Chat chat) {
        if (!TextUtils.isEmpty(chat.media_path)) {
            try {
                File file = new File(chat.media_path);
                if (file.exists()) {
                    String new_media_path = ChatConfig.getFavoriteFolderPath() + file.getName();
                    Utils.copyFileOrThrow(file, new File(new_media_path));
                    chat.media_path = new_media_path;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        ContentValues contentValues = new ContentValues();
        contentValues.put(Columns.NAME, chat.name);
        contentValues.put(Columns.TYPE, chat.type);
        contentValues.put(Columns.READ, chat.read);
        contentValues.put(Columns.SENT, chat.sent);
        contentValues.put(Columns.MESSAGE_TYPE, chat.message_type);
        contentValues.put(Columns.MESSAGE_TEXT, chat.message_text);
        contentValues.put(Columns.MEDIA_PATH, chat.media_path);
        contentValues.put(Columns.SERVER_MEDIA_PATH, chat.server_media_path);
        contentValues.put(Columns.VOICE_LENGTH, chat.voice_length);
        contentValues.put(Columns.TIME_STAMP, System.currentTimeMillis());
        return contentResolver.insert(Columns.FAVORITE_CONTENT_URI, contentValues);
    }

    @Override
    public String toString() {
        return "id = " + id + "; name = " + name + "; type = " + type + "; read = " + read
                + "; sent = " + sent + "; message_type = " + message_type + "; message_text = "
                + message_text + "; media_path = " + media_path + "; server_media_path = "
                + server_media_path + "; voice_length = " + voice_length + "; timestampe = "
                + time_stamp;
    }
}
